package domain;

import interfaces.ICardManagement;

import java.io.IOException;
import java.io.Serializable;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.Vector;

import persistence.FilePersistenceManager;
import persistence.IPersistenceManager;
import valueObjects.game.card.Card;

/**
 * This class is for managing the cards used by this game
 */
public class CardManagement implements Serializable, ICardManagement{
	
	private static final long serialVersionUID = 1L;
	// stack for treasurecards
	private Vector<Card> treasureCards = new Vector<Card>();
	// stack for doorCards
	private Vector<Card> doorCards = new Vector<Card>();
	// stack for deposit the treasure cards
	private Vector<Card> depositStackTreasureCards = new Vector<Card>();
	// stack for deposit the door cards
	private Vector<Card> depositStackDoorCards = new Vector<Card>();
	
	private transient IPersistenceManager pManager = new FilePersistenceManager();
	// where the path to the resources are stored
	private String fileResource;


	/**
	 * Constructor with the main file where all the resources are defined
	 * @param mainFile
	 * @param loadImages whether to load images for the cards
	 */
	public CardManagement(String mainFile) {
		this.fileResource = mainFile;
		this.loadCards();
	}

	/* (non-Javadoc)
	 * @see domain.ICardManagement#getTreasureCards()
	 */
	@Override
	public List<Card> getTreasureCards() {
		return this.treasureCards;
	}
	
	/* (non-Javadoc)
	 * @see domain.ICardManagement#getDoorCards()
	 */
	@Override
	public List<Card> getDoorCards() {
		return this.doorCards;
	}

	/**
	 * Loads an equipmentcards from the EquipCards.txt file and adds it to the treasureCards list
	 * @param file
	 * @throws IOException
	 */
	private void loadEquipmentCards(String file) throws IOException {
		pManager.openForReading(file);
		// loading equipment cards
		Card c;
		do {
			c = pManager.loadEquipCard();
			if(c != null && c.isCard()){
				this.treasureCards.add(c);
			}
		}while(c != null);
		pManager.close();
	}

	/**
	 * Loads racecards from the CharacterRaceCards.txt file and adds it to the doorCards list
	 * @param file
	 * @throws IOException
	 */
	private void loadRaceCards(String file) throws IOException {
		pManager.openForReading(file);
		// loading race cards
		Card c;
		do {
			c = pManager.loadRaceCard();
			if(c != null && c.isCard()){
				this.doorCards.add(c);
			}
		}while(c != null);
		pManager.close();
	}

	
	/**
	 * Loads classcards from the CharacterClassCards.txt file and adds it to the doorCards list
	 * @param file
	 * @throws IOException
	 */
	private void loadClassCards(String file) throws IOException {
		pManager.openForReading(file);
		// loading class cards
		Card c;
		do {
			c = pManager.loadClassCard();
			if(c != null && c.isCard()){
				this.doorCards.add(c);
			}
		}while(c != null);
		pManager.close();
	}

	/**
	 * Loads cursecards from the CurseCards.txt file and adds it to the doorCards list
	 * @param file
	 * @throws IOException
	 */
	private void loadCurseCards(String file) throws IOException {
		pManager.openForReading(file);
		// loading curse card
		Card c;
		do {
			c = pManager.loadCurseCard();
			if(c != null && c.isCard()){
				this.doorCards.add(c);
			}
		}while(c != null);
		pManager.close();
	}

	/**
	 * Loads buffcards from the BuffCards.txt file and adds it to the treasureCards list
	 * @param file
	 * @throws IOException
	 */
	private void loadBuffCards(String file) throws IOException {
		pManager.openForReading(file);
		// loading buff cards
		Card c;
		do {
			c = pManager.loadBuffCard();
			if(c != null && c.isCard()){
				this.treasureCards.add(c);
			}
		}while(c != null);
		pManager.close();
	}

	/**
	 * Loads monstercards from the MonsterCards.txt file and adds it to the doorCards list
	 * @param file
	 * @throws IOException
	 */
	private void loadMonsterCards(String file) throws IOException {
		pManager.openForReading(file);
		// loading monster cards
		Card c;
		do {
			c = pManager.loadMonsterCard();
			if(c != null && c.isCard()){
				this.doorCards.add(c);
			}
		}while(c != null);
		pManager.close();
	}
	
	/**
	 * Loads miscellaneous cards from the MiscellaneousCards.txt file and adds it to the treasureCards list
	 * @param file
	 * @throws IOException
	 */
	private void loadMiscellaneousCards(String file) throws IOException {
		pManager.openForReading(file);
		// loading miscellaneous cards
		Card c;
		do {
			c = pManager.loadMiscellaneousCard();
			if(c != null && c.isCard()){
				this.treasureCards.add(c);
			}
		}while(c != null);
		pManager.close();
	}

	public void loadCards() {

		try {
			pManager.openForReading(this.fileResource);
			List<String> fileSource = new ArrayList<String>();
			boolean linesLeft = true;
			while (linesLeft) {
				String readLine = pManager.readLine();
				if (readLine != null) {
					String line[] = readLine.split(":");
					fileSource.add(line[1]);
				} else {
					linesLeft = false;
				}
			}
			pManager.close();

			this.loadBuffCards(fileSource.get(0));
			this.loadClassCards(fileSource.get(1));
			this.loadRaceCards(fileSource.get(2));
			this.loadCurseCards(fileSource.get(3));
			this.loadEquipmentCards(fileSource.get(4));
			this.loadMonsterCards(fileSource.get(5));
			this.loadMiscellaneousCards(fileSource.get(6));
			Collections.shuffle(this.doorCards);
			Collections.shuffle(this.treasureCards);
		} catch (IOException e) {
			e.printStackTrace();
		}
		
	}


	/* (non-Javadoc)
	 * @see domain.ICardManagement#getPickUpStackDoorCards()
	 */
	@Override
	public Vector<Card> getPickUpStackDoorCards() {
		return this.doorCards;
	}
	
	/* (non-Javadoc)
	 * @see domain.ICardManagement#getPickUpStackTreasureCards()
	 */
	@Override
	public Vector<Card> getPickUpStackTreasureCards() {
		return this.treasureCards;
	}
	
	
	/* (non-Javadoc)
	 * @see domain.ICardManagement#getOneCardFromTreasurePickUpStack()
	 */
	@Override
	public Card getOneCardFromTreasurePickUpStack() {
		Card treasureCard = null;
		if(this.treasureCards.isEmpty()){
			Collections.shuffle(this.depositStackTreasureCards);
			this.treasureCards = this.depositStackTreasureCards;
			this.depositStackTreasureCards = new Vector<Card>();
		}
		treasureCard = this.treasureCards.lastElement();
		this.treasureCards.removeElement(treasureCard);
		return treasureCard;
	}
	
	/* (non-Javadoc)
	 * @see domain.ICardManagement#getOneCardFromDoorPickUpStack()
	 */
	@Override
	public Card getOneCardFromDoorPickUpStack() {
		Card doorCard = null;
		if(this.doorCards.isEmpty()){
			Collections.shuffle(this.depositStackDoorCards);
			this.doorCards = this.depositStackDoorCards;
			this.depositStackDoorCards = new Vector<Card>();
		}
		doorCard = this.doorCards.lastElement();
		this.doorCards.removeElement(doorCard);
		return doorCard;
	}

	/* (non-Javadoc)
	 * @see domain.ICardManagement#addDepositDoorCard(valueObjects.game.card.Card)
	 */
	@Override
	public void addDepositDoorCard(Card c) {
		this.depositStackDoorCards.add(c);
	}

	/* (non-Javadoc)
	 * @see domain.ICardManagement#addDepositStackTreasureCards(valueObjects.game.card.Card)
	 */
	@Override
	public void addDepositTreasureCard(Card c) {
		this.depositStackTreasureCards.add(c);
	}

}
